package com.hsgene.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hsgene.common.util.basic.JsonUtils;
import com.hsgene.common.util.basic.UUID32;
import com.hsgene.common.util.character.CharactersConstant;
import com.hsgene.common.util.http.HttpConnectionManager;
import com.hsgene.common.util.qiniu.QiniuCertificateUtil;
import com.hsgene.common.util.result.ApiResult;
import com.hsgene.order.domain.billing.dto.*;
import com.hsgene.order.persistence.AppletsOrderRepository;
import com.hsgene.order.persistence.InvoiceOpenRepository;
import com.hsgene.order.service.InvoiceOpenService;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 开票申请service
 *
 * @author wxf
 * @date 2018/11/2 11:59
 **/
@Service
public class InvoiceOpenServiceImpl implements InvoiceOpenService {

    /**
     * Log
     */
    private static Logger LOGGER = LogManager.getLogger(InvoiceOpenServiceImpl.class);

    @Resource
    private InvoiceOpenRepository invoiceOpenRepository;

    @Resource
    private AppletsOrderRepository appletsOrderRepository;

    @Resource
    private HttpConnectionManager httpConnectionManager;

    @Value("${billing.url}")
    private String billingUrl;

    /**
     * 查询开票申请列表
     *
     * @param con 查询条件
     * @return
     */
    @Override
    public BillingApplySumInfoDto queryApplyBilling(BillingApplyConditionDto con) {
        //获取列表
        List<BillingApplyListInfoDto> applyListInfoDtos = invoiceOpenRepository.queryApplyBilling(con);
        BillingApplySumInfoDto totalInfoDto = new BillingApplySumInfoDto();
        totalInfoDto.setApplyListInfoDtos(applyListInfoDtos);
        //获取总数、总页数
        Integer sumCount = invoiceOpenRepository.getApplyBillingCount(con);
        if (sumCount == null) {
            totalInfoDto.setSumCount(0);
            totalInfoDto.setTotalPage(0);
            return totalInfoDto;
        }
        totalInfoDto.setSumCount(sumCount);
        Integer size = con.getSize();
        totalInfoDto.setTotalPage(sumCount % size == 0 ? sumCount / size : sumCount / size + 1);
        return totalInfoDto;
    }

    /**
     * 修改发票信息
     *
     * @param infoDto 发票信息
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    public Boolean updateInvoice(OrderInvoiceInfoDto infoDto) {
        try {
            //校验发票是否存在
            OrderInvoiceInfoDto invoiceInfoDto = invoiceOpenRepository.getOrderInvoice(infoDto.getOrderId());
            if (invoiceInfoDto == null) {
                //不存在则插入
                infoDto.setInvoiceId(UUID32.randomUUIDString());
                return invoiceOpenRepository.inserInvoiceInfo(infoDto);
            }
            //存在则更新
            Boolean result = invoiceOpenRepository.updateInvoice(infoDto);
            return result != null;
        } catch (Exception e) {
            LOGGER.error("update invoice is error...", e);
            return false;
        }
    }

    /**
     * 获取订单开票信息
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public OrderApplyBillingInfoDto getApplyBillingDetails(String orderId) {
        Integer flag = appletsOrderRepository.checkOrderIsEffect(orderId, null);
        if (flag == null) {
            return null;
        }
        return invoiceOpenRepository.getApplyBillingDetails(orderId);
    }

    /**
     * 校验发票信息是否完整
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public Boolean getOrderInvoice(String orderId) {
        OrderInvoiceInfoDto invoiceInfoDto = invoiceOpenRepository.getOrderInvoice(orderId);
        //反射判断属性为空则数据不完成
        if (invoiceInfoDto == null) {
            LOGGER.error("invoice info is not exists...");
            return false;
        }
        Integer invoiceType = invoiceInfoDto.getInvoiceType();
        if (invoiceType == null) {
            LOGGER.error("invoice type is not null...");
            return false;
        }
        if (StringUtils.isEmpty(invoiceInfoDto.getInvoiceName())) {
            LOGGER.error("invoice name is not null...");
            return false;
        }
        //企业
        if (invoiceType == 0) {
            return true;
        }
        //企业凭证
        List<String> voucher = invoiceInfoDto.getEnterpriseSealVoucher();
        if (voucher == null || voucher.isEmpty() || voucher.size() > 1) {
            LOGGER.error("invoice voucher is not null and size only one...");
            return false;
        }
        //纳税号
        if (StringUtils.isEmpty(invoiceInfoDto.getTaxesNo())) {
            LOGGER.error("invoice taxesNo is not null...");
            return false;
        }
        return true;
    }

    /**
     * 判断是否是个人发票
     *
     * @param orderIds 订单id
     * @return
     */
    @Override
    public List<OrderPersonBillingDto> checkOrderIsOneSelf(List<String> orderIds) {
        return invoiceOpenRepository.checkOrderIsOneSelf(orderIds);
    }

    /**
     * 申请开票
     *
     * @param orderId 订单id
     */
    @Override
    public ApiResult applyBilling(String orderId) {
        BillingApplyParamsDto paramsDto = invoiceOpenRepository.getApplyBillingParams(orderId);
        String jsonStr = JsonUtils.objectToJson(paramsDto);
        List<String> orderIds = new ArrayList<>();
        orderIds.add(orderId);
        //发送申请
        return sendApply(jsonStr, orderIds);
    }

    /**
     * 合并申请开票
     *
     * @param orderIds 订单ids
     * @return
     */
    @Override
    public ApiResult mergeApplyBilling(List<String> orderIds) {
        BillingApplyParamsDto paramsDto = new BillingApplyParamsDto();
        for (int i = 0; i < orderIds.size(); i++) {
            BillingApplyParamsDto temp = invoiceOpenRepository.getApplyBillingParams(orderIds.get(i));
            //取第一个值赋值
            if (i == 0) {
                BeanUtils.copyProperties(temp, paramsDto);
                continue;
            }
            paramsDto.setTotalAmount(paramsDto.getTotalAmount() + temp.getTotalAmount());
            paramsDto.getBusinessInfo().addAll(temp.getBusinessInfo());
        }
        String jsonStr = JsonUtils.objectToJson(paramsDto);
        return sendApply(jsonStr, orderIds);
    }

    /**
     * 获取发票信息
     *
     * @param orderId 订单ID
     * @return
     */
    @Override
    public OrderInvoiceInfoDto getInvoiceInfo(String orderId) {
        OrderInvoiceInfoDto invoiceInfoDto = invoiceOpenRepository.getOrderInvoice(orderId);
        if (invoiceInfoDto == null) {
            return null;
        }
        List<String> sealVoucher = invoiceInfoDto.getEnterpriseSealVoucher();
        if (sealVoucher == null || sealVoucher.isEmpty()) {
            return invoiceInfoDto;
        }
        //企业凭证加签
        invoiceInfoDto.setEnterpriseSealVoucher(QiniuCertificateUtil.getDownloadCertificateList(sealVoucher));
        return invoiceInfoDto;
    }

    private ApiResult sendApply(String jsonStr, List<String> orderIds) {
        String result = httpConnectionManager.doPost(jsonStr, billingUrl, CharactersConstant.UTF_8);
        JSONObject json = JSONObject.parseObject(result);
        if (Integer.parseInt(json.getString("status")) == 200 && (Boolean) json.get("success")) {
            //发送成功之后，更新开票申请时间，开票状态变为待开票
            invoiceOpenRepository.updateApplyTime(orderIds, new Date());
            return new ApiResult(200, "success", "申请成功", json.get("success"));
        }
        return new ApiResult(Integer.parseInt(json.getString("status")), "failed", "开票申请失败", json.getString("message"));
    }

}
